#include "../corelib/redis/redis.hh"
#include "../corelib/time_util.hh"
#include "unittest/unittest.hh"
#include <cstring>
#include <cstdlib>
#include <chrono>

//
// NOTICE open testcases of Redis, please startup a Redis server with listening at 127.0.0.1:6379
//

using namespace kratos::redis;

FIXTURE_BEGIN(Redis)

CASE(TestAddHost) {
    ASSERT_TRUE(RedisRef.addHost("123", "127.0.0.2"));
    ASSERT_FALSE(RedisRef.addHost("", "127.0.0.2"));
    ASSERT_TRUE(RedisRef.removeHost("123"));
    ASSERT_FALSE(RedisRef.removeHost("456"));
}

CASE(TestFindConn) {
    ASSERT_TRUE(RedisRef.addHost("123", "127.0.0.2"));
    ASSERT_FALSE(RedisRef.findConn("123"));
    ASSERT_TRUE(RedisRef.removeHost("123"));

    ASSERT_TRUE(RedisRef.addHost("123", "localhost"));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    ASSERT_TRUE(RedisRef.findConn("123"));
    ASSERT_TRUE(RedisRef.removeHost("123"));
}

CASE(TestDoCommand1) {
    ASSERT_TRUE(RedisRef.addHost("123", "localhost"));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    ASSERT_TRUE(RedisRef.findConn("123"));
    auto& conn = RedisRef.findConn("123");
    bool done = false;
    ASSERT_TRUE(conn.doCommand("sdjfkdjf", 1, 1, 0, [&](RedisResult& result, RedisConn& conn) {
        done = result.getUserData() == 1;
    }, nullptr, nullptr));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    RedisRef.update(kratos::corelib::TimeUtil::getMillionSecondsTimestampOS());
    ASSERT_TRUE(done);
    ASSERT_TRUE(RedisRef.removeHost("123"));
}

CASE(TestDoCommand2) {
    ASSERT_TRUE(RedisRef.addHost("123", "127.0.0.2"));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    ASSERT_FALSE(RedisRef.findConn("123"));
    auto& conn = RedisRef.findConn("123");
    bool done = false;
    ASSERT_TRUE(conn.doCommand("sdjfkdjf", 1, 1, 800, nullptr, [&](RedisResult& result, RedisConn& conn) {
        done = true;
    }, nullptr));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    RedisRef.update(kratos::corelib::TimeUtil::getMillionSecondsTimestampOS());
    ASSERT_TRUE(done);
    ASSERT_TRUE(RedisRef.removeHost("123"));
}

CASE(TestDoCommand3) {
    ASSERT_TRUE(RedisRef.addHost("123", "127.0.0.1"));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    auto& conn = RedisRef.findConn("123");
    int count = 0;
    for (int i = 0; i < 10; i++) {
        ASSERT_TRUE(conn.doCommand("keys a", 1, 1, 0, [&](RedisResult& result, RedisConn& conn) {
            count++;
        }, nullptr, nullptr));
    }
    std::this_thread::sleep_for(std::chrono::seconds(2));
    RedisRef.update(kratos::corelib::TimeUtil::getMillionSecondsTimestampOS());
    ASSERT_TRUE(count == 10);
    ASSERT_TRUE(RedisRef.removeHost("123"));
}

CASE(TestDoCommand4) {
    ASSERT_TRUE(RedisRef.addHost("123", "127.0.0.1"));
    std::this_thread::sleep_for(std::chrono::seconds(1));
    auto& conn = RedisRef.findConn("123");
    ASSERT_FALSE(conn.doCommand("", 1, 1, 0, nullptr, nullptr, nullptr));
    ASSERT_FALSE(conn.doCommand("111", 0, 0, 0, nullptr, nullptr, nullptr));
    ASSERT_TRUE(RedisRef.removeHost("123"));
}

FIXTURE_END(Redis)
